package com.probiz.estore.common.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.probiz.estore.Constants;
import com.probiz.estore.cart.util.ShoppingCartUtil;
import com.probiz.estore.common.model.cart.Shoppingcart;
import com.probiz.estore.common.model.cart.ShoppingcartItem;
import com.probiz.estore.common.model.customer.Address;
import com.probiz.estore.common.model.order.CheckoutSession;
import com.probiz.estore.common.model.order.SalesOrder;
import com.probiz.estore.common.model.product.Product;
import com.probiz.estore.common.model.product.ProductSku;
import com.probiz.estore.common.model.sales.GiftCertificate;
import com.probiz.estore.common.model.system.PaymentMethod;
import com.probiz.estore.common.model.system.SelfCollectionCentre;
import com.probiz.estore.common.model.system.ShippingMethod;
import com.probiz.estore.common.model.system.ShippingRate;
import com.probiz.estore.common.model.system.TaxRate;
import com.probiz.estore.common.model.system.Wrap;
import com.probiz.estore.common.service.CheckoutService;
import com.probiz.estore.common.service.ProductService;
import com.probiz.estore.common.service.PromoService;
import com.probiz.estore.core.util.I18nUtil;
import com.probiz.estore.customer.service.AddressManager;
import com.probiz.estore.exception.CheckoutException;
import com.probiz.estore.exception.GiftCertificateStateException;
import com.probiz.estore.exception.OrderProccessFlowException;
import com.probiz.estore.exception.OutOfStockException;
import com.probiz.estore.exception.ShopPointConsumptionException;
import com.probiz.estore.order.service.OrderProcessFlowManager;
import com.probiz.estore.product.service.ProductSkuManager;
import com.probiz.estore.sales.service.GiftCertificateManager;
import com.probiz.estore.system.service.PaymentMethodManager;
import com.probiz.estore.system.service.SelfCollectionCentreManager;
import com.probiz.estore.system.service.ShippingMethodManager;
import com.probiz.estore.system.service.ShippingRateManager;
import com.probiz.estore.system.service.TaxRateManager;
import com.probiz.estore.system.service.WrapManager;
import com.probiz.estore.system.service.impl.SystemServiceImpl;
import com.probiz.estore.webapp.util.RequestContext;

public class CheckoutServiceImpl implements CheckoutService {
	
	private ShippingRateManager shippingRateManager;
	private TaxRateManager taxRateManager;
	private WrapManager wrapManager;
	private ShippingMethodManager shippingMethodManager;
	private PaymentMethodManager paymentMethodManager;
	private OrderProcessFlowManager orderProcessFlowManager;
	private PromoService promoService;
	private GiftCertificateManager giftCertificateManager;
	private AddressManager addressManager;
	private ProductSkuManager productSkuManager;
	private SelfCollectionCentreManager selfCollectionCentreManager;
	private ProductService productService;
	
	public void setProductService(ProductService productService) {
		this.productService = productService;
	}


	private static final Log logger = LogFactory.getLog(SystemServiceImpl.class);
	
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.common.service.CheckoutService#doPlaceOrder(com.probiz.estore.common.model.order.CheckoutSession)
	 */
	public SalesOrder doPlaceOrder(CheckoutSession checkoutSession) throws OutOfStockException, GiftCertificateStateException, ShopPointConsumptionException,CheckoutException {
		//数据校验(不通过会抛出运行时异常)
		checkoutSession.test();
		
		//结帐前预处理准备。例如重新计算购物车中的促销信息、重新计算税等
		doPreprocess4PlaceOrder(checkoutSession);
		
		//下订单
		SalesOrder salesOrder = orderProcessFlowManager.createSalesOrder(checkoutSession);	
		
		
		//-------------如果是前台-----------
		if(RequestContext.isFront()){
			//如果该用户为登陆用户，并且之前没有运输地址，则将该地址保存为默认的运输地址
			this.saveCustomerAddress(checkoutSession);
			//清空购物车
			ShoppingCartUtil.getInstance().clearCurrentUserShoppingcart();
		}
		CheckoutSession.clear();
		return salesOrder;
		
	}
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.common.service.CheckoutService#doEditOrder(com.probiz.estore.common.model.order.SalesOrder, com.probiz.estore.common.model.order.CheckoutSession)
	 */
	public void doEditOrder(SalesOrder salesOrder,CheckoutSession checkoutSession) throws OutOfStockException, GiftCertificateStateException, ShopPointConsumptionException,OrderProccessFlowException,CheckoutException{
		//数据校验(不通过会抛出运行时异常)
		checkoutSession.test();
		
		//预处理准备。例如重新计算购物车中的促销信息、重新计算税等
		doPreprocess4PlaceOrder(checkoutSession);
		
		//编辑
		orderProcessFlowManager.doEditOrder(salesOrder, checkoutSession);	
		
	}

	//下单前预处理
	private void doPreprocess4PlaceOrder(CheckoutSession checkoutSession) {
		Shoppingcart shoppingcart = checkoutSession.getShoppingcart();
		
		//更新购物车中的数据
		for (ShoppingcartItem shoppingcartItem: shoppingcart.getProductItems()) {
			ProductSku productSku = shoppingcartItem.getProductSku();
			productSku = productSkuManager.getProductSkuPojoByProductSkuCode(productSku.getProductSkuCode());
			shoppingcartItem.setProductSku(productSku);
			shoppingcartItem.calculateSalesAndWholesalePrice();
		}
		
		//重新计算促销优惠
		if (!checkoutSession.isAnonymousUser()) {
			shoppingcart = promoService.appendPromoInfo(shoppingcart, shoppingcart.getOwner());
		}
		
		//重新计算税
		caculateTaxes(shoppingcart, Integer.valueOf(checkoutSession.getRegionId()));
	}
	
	
	
	
	//保存用户地址
	private void saveCustomerAddress(CheckoutSession checkoutSession) {
		if (checkoutSession.isAnonymousUser()) {
			return;
		}
		List<Address> list = addressManager.getAllShippingAddressByAppuserId(checkoutSession.getShoppingcart().getCustomerId());
		if (list.size() != 0) {
			return;
		}
		
		Address address = checkoutSession.generateAddress();
		address.setAppUser(checkoutSession.getShoppingcart().getOwner());
		address.setIsDefaultBillingAddress(Constants.FLAG_FALSE);
		address.setIsDefaultShippingAddress(Constants.FLAG_TRUE);
		address.setAddressType(Constants.ADDRESS_TYPE_SHIPPING);
		addressManager.save(address);
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.common.service.CheckoutService#getRegionShippingRates(java.lang.Boolean, java.lang.Integer)
	 */
	public List<ShippingRate> getRegionShippingRates(Boolean isCod, Integer regionId) {
		return shippingRateManager.getDifferentShipMethodRatesByRegionId(isCod, regionId);
	}
	/**
	 * 根据费率的id和商品重量，返回运输费用
	 * @param Integer 费率id(ShippingRate.shippingRateId)
	 * @param weight 商品重量
	 * @return
	 */
	public BigDecimal getShippingExpence(Integer shippingRateId,BigDecimal weight) {
		return shippingRateManager.getShippingExpence(shippingRateId, weight);
	}
	
	/**
	 * 查询所有当前系统定义有的包装方式
	 * @return
	 */
	public List<Wrap> getSystemWraps() {
		return wrapManager.listAll();
	}
	public void setShippingRateManager(ShippingRateManager shippingRateManager) {
		this.shippingRateManager = shippingRateManager;
	}
	public void setWrapManager(WrapManager wrapManager) {
		this.wrapManager = wrapManager;
	}
	public Wrap getWrapById(Integer wrapId) {
		return wrapManager.getById(wrapId);
	}
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.common.service.CheckoutService#caculateTaxes(com.probiz.estore.common.model.cart.Shoppingcart, java.lang.Integer)
	 */
	public void caculateTaxes(Shoppingcart shoppingcart,Integer regionId){
		
		shoppingcart.resetTax();
		List<ShoppingcartItem> shoppingcartItems = shoppingcart.getProductItems();
		HashMap<Integer, List<TaxRate>> productTaxRateMap = new HashMap<Integer, List<TaxRate>>();		// {productTypeId,List<TaxRate>}
		for (ShoppingcartItem shoppingcartItem : shoppingcartItems) {
			Integer productTypeId = shoppingcartItem.getProductSku().getProduct().getProductTypeId();	// 可能有null pointer导常
			List<TaxRate> taxRateList = productTaxRateMap.get(productTypeId);
			if (taxRateList == null) {
				taxRateList = taxRateManager.getTaxRateListByRegionIdAndProductTypeId(regionId, productTypeId);
				productTaxRateMap.put(productTypeId, taxRateList);
			}
			if (taxRateList.size() > 0) {
				BigDecimal tax = new BigDecimal(0);
				StringBuffer taxName = new StringBuffer();
				BigDecimal itemPrices = shoppingcartItem.getDiscountPrice()
						.multiply(BigDecimal.valueOf(shoppingcartItem.getQuantity()));// shoppingcartItem折后价总和
				for (TaxRate taxRate : taxRateList) {
					tax = tax.add(itemPrices.multiply(taxRate.getRateValue()).divide(BigDecimal.valueOf(100)));
					taxName.append(taxRate.getTax().getTaxName()).append(",");// 多个税率间用逗号分隔
					// System.out.println(":::::::::::::"+taxRate.getRateValue());
				}
				taxName.deleteCharAt(taxName.length() - 1);
				shoppingcartItem.setTax(tax.setScale(2, BigDecimal.ROUND_HALF_UP));
				shoppingcartItem.setTaxName(taxName.toString());
				// System.out.println("【itemPrices="+itemPrices+",taxName=taxName+"taxRate.getRateValue"+",tax="+tax+"】,skuId="+shoppingcartItem.getProductSku().getId());
			}
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.common.service.CheckoutService#getSelfCollectionCentreListByRegionId(java.lang.Integer)
	 */
	public List<SelfCollectionCentre> getSelfCollectionCentreListByRegionId(Integer regionId){
		return selfCollectionCentreManager.getSelfCollectionCentreListByRegionId(regionId);
	}
	
	public SelfCollectionCentre getSelfCollectionCentreById(Integer selfCollectionCentreId) {
		return selfCollectionCentreManager.getById(selfCollectionCentreId);
	}

	public PaymentMethod getPaymentMethodById(Integer paymentMethodId) {
		return paymentMethodManager.getById(paymentMethodId);
	}
	
	public ShippingMethod getShippingMethodById(Integer id) {
		return shippingMethodManager.getById(id);
	}
	
	public List<ShippingMethod> getShippingMethodList() {
		return shippingMethodManager.listAllActive();
	}
	
	public void setTaxRateManager(TaxRateManager taxRateManager) {
		this.taxRateManager = taxRateManager;
	}
	
	public ShippingRate getShippingRateById(Integer id) {
		return shippingRateManager.getById(id);
	}
	
	public GiftCertificate getGiftCertificateByNo(String no) {
		return giftCertificateManager.getGiftCertificate(no);
	}

	public void setShippingMethodManager(ShippingMethodManager shippingMethodManager) {
		this.shippingMethodManager = shippingMethodManager;
	}

	public void setPaymentMethodManager(PaymentMethodManager paymentMethodManager) {
		this.paymentMethodManager = paymentMethodManager;
	}

	public void setPromoService(PromoService promoService) {
		this.promoService = promoService;
	}


	public void setOrderProcessFlowManager(OrderProcessFlowManager orderProcessFlowManager) {
		this.orderProcessFlowManager = orderProcessFlowManager;
	}


	public void setGiftCertificateManager(GiftCertificateManager giftCertificateManager) {
		this.giftCertificateManager = giftCertificateManager;
	}

	public void setAddressManager(AddressManager addressManager) {
		this.addressManager = addressManager;
	}

	public void setProductSkuManager(ProductSkuManager productSkuManager) {
		this.productSkuManager = productSkuManager;
	}

	public void setSelfCollectionCentreManager(SelfCollectionCentreManager selfCollectionCentreManager) {
		this.selfCollectionCentreManager = selfCollectionCentreManager;
	}

	public boolean isTaxEnabled() {
		Long count = taxRateManager.countAll();
		if (count > 0) {
			return true;
		} else {
			return false;
		}
	}
	
	public Shoppingcart validationDeleted(HttpServletRequest request,
			HttpServletResponse response, Shoppingcart shoppingcart) {
		//下架后可以下订单的BUG处理
		Set<ShoppingcartItem> scis = shoppingcart.getShoppingCartItems();
		List<ShoppingcartItem> delList = new ArrayList<ShoppingcartItem>();
		String delProducts = "";
		for (ShoppingcartItem sci :scis) {
			if (null != sci.getProductSku()) {//虚拟物品
				Product pt = productService.getById(sci.getProductSku().getProductId());
				if (pt == null || (pt != null && !Constants.FLAG_TRUE.equals(pt.getStatus()))) {
					delList.add(sci);
					delProducts = sci.getProductSku().getProduct().getProductName() + ",";
				}
			}
		}
		scis.removeAll(delList);
		if (StringUtils.isNotEmpty(delProducts)) {
			delProducts = delProducts.substring(0, delProducts.length() - 1);
			String msg = I18nUtil.getInstance().getMessage("shoppingcart.exceptionMsg",new Object[]{delProducts});
			request.setAttribute("exceptionMsg", msg);
		}
		ShoppingCartUtil.getInstance().updateShoppingcartCookie(shoppingcart, response);
		return shoppingcart;
	}
}